import {reactive, type Ref, ref} from "vue";
import {getUserInfo} from '@/api/account'
import {getToken, loadToken, signout} from '@/soar/utils/token'
import {getCurrentRoute, hasPrevPage} from "@/soar/utils/uniUtils";
import message from "@/soar/utils/message";

const loginPath = '/pages/anon/login';

const ROLE_KEY = '$:roles'
const PERMIT_KEY = '$:permits'

type State = {
	superAdministrator: boolean | null;
	user: { [k: string]: any } | null;
}

const state = reactive<State>({
	superAdministrator: null,
	user: null,
});

/**
 * 获取当前用户信息
 */
export async function getUser(): Promise<State['user']> {
	if (!state.user) {
		await loadAccountInfo();
	}
	return JSON.parse(JSON.stringify(state.user));
}

/**
 * 获取角色列表
 */
export async function getRoles(): Promise<string[]> {
	const list = uni.getStorageSync(ROLE_KEY);
	if (list) {
		return list;
	}
	return loadAccountInfo().then(res => {
		return res.roles;
	})
}

/**
 * 获取权限列表
 */
export async function getPermits(): Promise<string[]> {
	const list = uni.getStorageSync(PERMIT_KEY);
	if (list) {
		return list;
	}
	return loadAccountInfo().then(res => {
		return res.permits;
	})
}

/**
 * 是否已登录
 */
export async function isLogin() {
	if (state.user) {
		return;
	}
	return loadAccountInfo().then(() => {
		return
	})
}

/**
 * 是否是超级管理员
 */
export async function isSuperAdministrator() {
	if (state.superAdministrator === null) {
		await loadAccountInfo();
	}
	return state.superAdministrator;
}

/**
 * 是否是指定用户类型
 * @param types 用户类型
 */
export function hasUserType(types: number | number[]) {
	return isLogin().then(() => {
		if (typeof types === 'number') {
			types = [ types ]
		}
		return getUser().then((res) => {
			// @ts-ignore
			if (types.includes(res?.userType)) {
				return;
			}
			throw '无权限';
		})
	})
}

/**
 * 是否是指定角色
 * @param roles 角色
 */
export function hasRole(roles: string | string[]) {
	return isLogin().then(() => {
		if (typeof roles === 'string') {
			roles = [ roles ]
		}
		return getRoles().then((res) => {
			for (const role of roles) {
				if (res.includes(role)) {
					return;
				}
			}
			throw '无权限';
		})
	})
}

/**
 * 是否有指定权限
 * @param permits 权限码
 */
export function hasPermit(permits: string | string[]) {
	return isLogin().then(() => {
		if (typeof permits === 'string') {
			permits = [ permits ]
		}
		return getPermits().then((res) => {
			for (const permit of permits) {
				if (res.includes(permit)) {
					return;
				}
			}
			throw '无权限';
		})
	})
}

/**
 * 使用是否登录标志【用于控制页面元素】
 */
export function useIsLogin() {
	const flag = ref(false);
	isLogin().then(() => {
		flag.value = true;
	}).catch(() => {
		flag.value = false;
	})
	return flag;
}

/**
 * 使用是否超级管理员标志【用于控制页面元素】
 */
export function useIsSuperAdministrator() {
	const flag = ref(false);
	isSuperAdministrator().then(() => {
		flag.value = true;
	}).catch(() => {
		flag.value = false;
	})
	return flag;
}

/**
 * 使用用户类型校验【用于控制页面元素】
 */
export function useHasUserType() {

	const has = ref((...types: number[]) => false);

	isLogin().then(() => {
		getUser().then(res => {
			// @ts-ignore
			has.value =  (...types: number[]) => {
				return types.includes(res?.userType);
			}
		})
	})

	return has;
}

/**
 * 使用角色校验【用于控制页面元素】
 */
export function useHasRole() {

	const has = ref((...roles: string[]) => false);

	isLogin().then(() => {
		getRoles().then(res => {
			// @ts-ignore
			has.value =  (...roles: string[]) => {
				for (const role of roles) {
					if (res.includes(role)) {
						return true;
					}
				}
				return false;
			}
		})
	})

	return has;
}

/**
 * 使用权限校验【用于控制页面元素】
 * @param parentPermit 父权限
 */
export function useHasPermit(parentPermit?: string) {

	const has = ref((...permits: string[]) => false);

	isLogin().then(() => {
		getPermits().then(res => {
			if (parentPermit) {
				res = res.filter(x => x.startsWith(parentPermit))
			}
			// @ts-ignore
			has.value =  (...permits: string[]) => {
				for (const permit of permits) {
					if (res.includes(parentPermit + permit)) {
						return true;
					}
				}
				return false;
			}
		})
	})

	return has;
}

/**
 * 定义权限
 */
interface Definition {
	/**
	 * 新增权限
	 */
	create?: string | string[] | 'create';
	/**
	 * 修改权限
	 */
	update?: string | string[] | 'update';
	/**
	 * 删除权限
	 */
	remove?: string | string[] | 'remove';
	/**
	 * 查看权限
	 */
	detail?: string | string[] | 'detail';
	/**
	 * 导入权限
	 */
	import?: string | string[] | 'import';
	/**
	 * 导出权限
	 */
	export?: string | string[] | 'export';
	/**
	 * 其他权限
	 */
	[permit: string]: string | string[];
}
/**
 * 使用权限（适用于重复判断权限的场景，提高性能，例如table每一行的操作列按钮权限控制；也适合统一管理权限，权限码变化时不用多处修改）
 * @param definition 权限配置，例：{ create: 'create', update: ['update'], edit: ['create', 'update'] }
 * @param parentPermit 父权限，默认当前菜单权限码
 */
export function usePermit<T extends Definition, R extends { [K in keyof T]: boolean }>(
	definition: T,
	parentPermit: string = '',
): R {
	// 初始化
	const map: any = {};
	for (const permit in definition) {
		map[permit] = false;
	}
	const res = reactive(map as R);
	// 权限判断
	isLogin().then(() => {
		getPermits().then(regs => {
			const has = (ps: string[]) => {
				for (let permit of ps) {
					permit = /^[a-zA-Z0-9].*$/.test(permit) ? `${parentPermit}${permit}` : permit;
					if (regs.includes(permit)) {
						return true;
					}
				}
				return false;
			};
			for (const permit in definition) {
				const ps = definition[permit];
				res[permit as keyof T] = has(Array.isArray(ps) ? ps : [ps]);
			}
		})
	})
	// 返回
	return res;
}

/**
 * 必须登录才能访问的页面，若未登录则跳到登录页
 */
export function mustLogin() {
	const promise = isLogin();
	promise.catch((err) => {
		message.error('请先登录');
		uni.reLaunch({ url: loginPath })
	})
	return promise;
}

/**
 * 无权限访问页面处理
 */
const noPermit = () => {
	message.error('无权限');
	if (hasPrevPage()) {
		// 返回上一页
		uni.navigateBack()
	} else {
		// 去首页
		uni.reLaunch({ url: '/' })
	}
};

/**
 * 必须超级管理员才能访问的页面，否则跳到登录页
 */
export function mustSuperAdministrator() {
	const promise = isSuperAdministrator();
	promise.catch(noPermit)
	return promise;
}

/**
 * 必须是指定用户类型才能访问的页面，若不是指定用户类型自动返回上一页
 * @param types 角色码
 */
export function mustHasUserType(types: number | number[]) {
	return mustLogin().then(() => {
		const promise = hasUserType(types);
		promise.catch(noPermit);
		return promise;
	})
}

/**
 * 必须是指定角色才能访问的页面，若不是角色自动返回上一页
 * @param roles 角色码
 */
export function mustHasRole(roles: string | string[]) {
	return mustLogin().then(() => {
		const promise = hasRole(roles);
		promise.catch(noPermit);
		return promise;
	})
}

/**
 * 必须有指定权限才能访问的页面，若无权限自动返回上一页
 * @param permits 权限码，默认页面路由
 */
export function mustHasPermit(permits = <string | string[]>[getCurrentRoute()]) {
	return mustLogin().then(() => {
		const promise = hasPermit(permits)
		promise.catch(noPermit);
		return promise;
	})
}

/**
 * 加载当前用户信息
 */
export function loadAccountInfo() {
	const promise = loadToken().then(() => {
		return getUserInfo(['user', 'role', 'permit']).then(res => {
			const d = res.data;
			state.superAdministrator = d.superAdministrator;
			state.user = d.user;
			uni.setStorageSync(ROLE_KEY, d.roles || []);
			uni.setStorageSync(PERMIT_KEY, d.permits || []);
			return d;
		})
	});
	promise.catch((err) => {
		removeAccountInfo();
		return err;
	})
	return promise;
}

/**
 * 删除当前用户信息
 */
export function removeAccountInfo() {
	signout();
	uni.removeStorageSync(ROLE_KEY);
	uni.removeStorageSync(PERMIT_KEY);
	for(const k in state) {
		// @ts-ignore
		state[k] = null;
	}
}
